/**
 * Author: Dmitry Ustimov
 * Date: 5/13/13
 * Time: 11:34 PM
 */

package com.gmail.dmitryustimov.ms.java7.patternslib.chain_of_responsibility.multyevent;

import java.util.HashMap;
import java.util.Map;

public abstract class Handler<T> {

    public Handler<T> next;
    private Map<Class<? extends T>, HandleAction<? extends T>> actions;

    public Handler() {
    }

    public Handler(Map<Class<? extends T>, HandleAction<? extends T>> mapHandleActions) {
        this.actions = new HashMap<>(mapHandleActions.size());
    }

    public void init(Map<Class<? extends T>, HandleAction<? extends T>> mapHandleActions) {
        this.actions = new HashMap<>(mapHandleActions);
    }

    public <E extends T> void handle(E request) {
        HandleAction<E> handleAction = getAction(((Class<E>)request.getClass()));
        if (handleAction != null) {
            if (canHandle(request)) {
                handleAction.handle(request);
            }
            else {
                if (next != null) {
                    next.handle(request);
                }
            }
        }
    }

    public <E extends T> void handleChain(E request) {
        HandleAction<E> handleAction = getAction(((Class<E>)request.getClass()));
        if (handleAction != null) {
            if (canHandle(request)) {
                handleAction.handle(request);
            }
            if (next != null) {
                next.handleChain(request);
            }
        }
    }

    private <E extends T> HandleAction<E> getAction(Class<E> clazz) {
        return (HandleAction<E>) actions.get(clazz);
    }

    public abstract Boolean canHandle(T request);

    public Handler<T> getNext() {
        return next;
    }

    public void setNext(Handler<T> next) {
        this.next = next;
    }
}
